package com.lu.wemedia.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.lu.api.article.IApArticleClient;
import com.lu.common.aliyun.GreenImageScan;
import com.lu.common.aliyun.GreenTextScan;
import com.lu.common.tess4j.Tess4jClient;
import com.lu.minio.service.FileStorageService;
import com.lu.model.article.dto.ArticleDto;
import com.lu.model.common.dtos.ResponseResult;
import com.lu.model.wemedia.pojo.WmChannel;
import com.lu.model.wemedia.pojo.WmNews;
import com.lu.model.wemedia.pojo.WmSenSitive;
import com.lu.model.wemedia.pojo.WmUser;
import com.lu.utils.common.SensitiveWordUtil;
import com.lu.wemedia.mapper.WmChannelMapper;
import com.lu.wemedia.mapper.WmNewsMapper;
import com.lu.wemedia.mapper.WmSensitiveMapper;
import com.lu.wemedia.mapper.WmUserMapper;
import com.lu.wemedia.service.IWmNewsAutoExamineService;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.tess4j.TesseractException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@Transactional
public class WmNewsAutoExamineServiceImpl implements IWmNewsAutoExamineService {

    @Autowired
    private WmNewsMapper wmNewsMapper;
    @Autowired
    private GreenTextScan greenTextScan;
    @Autowired
    private GreenImageScan greenImageScan;
    @Autowired
    private FileStorageService fileStorageService;
    @Autowired
    private IApArticleClient ApArticleClient;
    @Autowired
    private WmUserMapper wmUserMapper;
    @Autowired
    private WmChannelMapper wmChannelMapper;
    @Autowired
    private WmSensitiveMapper wmSenSitiveMapper;
    @Autowired
    private Tess4jClient tess4jClient;

    /**
     * 自媒体文章审核
     * @param id
     */
    @Async
    @Override
    public void autoExamine(Integer id) {
        //查询自媒体文章
        WmNews wmNews = wmNewsMapper.selectOne(Wrappers.<WmNews>lambdaQuery().eq(WmNews::getId, id));
        //校验
        if (wmNews == null) {
            throw new RuntimeException("WmNewsAutoScanServiceImpl-文章不存在");
        }
        //审核需要内容和图片
        if (wmNews.getStatus().equals(WmNews.Status.SUBMIT.getCode())) {
            //提取图片和文本内容
            Map<String, Object> data = ExtractTextAndImage(wmNews);

            //过滤文本内容敏感词
            boolean wordFlag = sensitiveFilte((String) data.get("text"), wmNews);
            if (!wordFlag) return;


            //审核文本内容
            boolean textFlag = extractTextAuto((String) data.get("text"), wmNews);
            if (!textFlag) {
                return;
            }

            //审核图片
            boolean imageFlag = extractImageAuto((List<String>) data.get("images"), wmNews);
            if (!imageFlag) {
                return;
            }
            //审核通过进行保存,调用feign的save，通过塔都article1的实现类保存方法
            ResponseResult responseResult = saveWmNews(wmNews);

            if (!responseResult.getCode().equals(200)) {
                throw new RuntimeException("文章审核通过,保存错误!");
            }
            //返回文章id
            wmNews.setArticleId((Long) responseResult.getData());
            extractUpdate(wmNews, (short) 9, "审核通过");
        }

}


    /**
     * 过滤文本内容敏感词
     * @param text
     * @param wmNews
     * @return
     */
    public boolean sensitiveFilte(String text, WmNews wmNews) {
        boolean flag = true;
        //获取敏感词字典
        List<WmSenSitive> senSitives = wmSenSitiveMapper.selectList(Wrappers.<WmSenSitive>lambdaQuery().select(WmSenSitive::getSensitives));
        List<String> list = senSitives.stream().map(WmSenSitive::getSensitives).collect(Collectors.toList());
        //初始化词库
        SensitiveWordUtil.initMap(list);
        //过滤
        Map<String, Integer> map = SensitiveWordUtil.matchWords(text);
        if (map.size() > 0) {
            extractUpdate(wmNews, (short) 2, "当前文章存在违规内容" + map);
            flag = false;
        }
        return flag;


    }

    /**
     * 审核通过后保存文章
     * @param wmNews
     */
    public ResponseResult saveWmNews(WmNews wmNews) {
        ArticleDto articleDto = new ArticleDto();
        BeanUtils.copyProperties(wmNews, articleDto);
        //字段名称不同需要手动设置
        //布局
        articleDto.setLayout(wmNews.getType());
        //频道
        WmChannel wmChannel = wmChannelMapper.selectOne(Wrappers.<WmChannel>lambdaQuery().eq(WmChannel::getId, wmNews.getChannelId()));
        if (wmChannel != null) {
            articleDto.setAuthorName(wmChannel.getName());
        }
        //作者id
        articleDto.setAuthorId(wmNews.getUserId().longValue());
        //作者姓名
        WmUser wmUser = wmUserMapper.selectOne(Wrappers.<WmUser>lambdaQuery().eq(WmUser::getId, wmNews.getUserId()));
        if (wmUser != null) {
            articleDto.setAuthorName(wmUser.getName());
        }
        //文章id
        if (wmNews.getArticleId() != null) {
            articleDto.setId(wmNews.getArticleId());
        }
        articleDto.setCreatedTime(new Date());

        //调用接口方法保存
        ResponseResult responseResult = ApArticleClient.saveArticle(articleDto);
        return responseResult;
    }


    /**
     * 图片审核
     * @param images
     * @param wmNews
     * @return
     */
    public boolean extractImageAuto(List<String> images, WmNews wmNews) {
        boolean flag = true;
        if (images.size() == 0 || images == null) {
            return flag;
        }
        //从minio下载图片并且去重
        images = images.stream().distinct().collect(Collectors.toList());

        //封装
        List<byte[]> result = new ArrayList<>();
            try {
                for (String image : images) {
                    byte[] bytes = fileStorageService.downLoadFile(image);
                    //过滤图片文字
                    ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
                    BufferedImage read = ImageIO.read(stream);
                    String data = null;
                    try {
                        data = tess4jClient.doOCR(read);
                    } catch (TesseractException e) {
                        e.printStackTrace();
                    }
                    //审核文字
                    boolean b = sensitiveFilte(data, wmNews);
                    if (!b) return b;
                    result.add(bytes);
                }
            }catch (IOException e) {
                e.printStackTrace();
            }

        try {
            Map map = greenImageScan.imageScan(result);
            if (map != null) {
                //审核失败
                if (map.get("suggestion").equals("block")) {
                    flag = false;
                    extractUpdate(wmNews, (short)2, "图片存在违规内容!");
                }
                //需要人工审核的
                if (map.get("suggestion").equals("review")) {
                    flag = false;
                    extractUpdate(wmNews, (short) 3, "当前图片存在不确定内容!需要人工审核!");
                }
            }
        } catch (Exception e) {
            flag = false;
            e.printStackTrace();
        }

        return flag;
    }


    /**
     * 文章内容审核
     * @param text
     * @param wmNews
     * @return
     */
    private boolean extractTextAuto(String text, WmNews wmNews) {
        boolean flag = true;
        //如果文本内容和标题都为空
        if ((wmNews.getContent() + wmNews.getTitle()).length() == 0) {
            return flag;
        }
        try {
            Map map = greenTextScan.greeTextScan(text);
            if (map != null) {
                //审核失败
                if (map.get("suggestion").equals("block")) {
                    flag = false;
                    extractUpdate(wmNews, (short)2, "文章存在违规内容!");
                }
                //需要人工审核的
                if (map.get("suggestion").equals("review")) {
                    flag = false;
                    extractUpdate(wmNews, (short) 3, "当前文章存在不确定内容!需要人工审核!");
                }
            }
        } catch (Exception e) {
            flag = false;
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 修改内容
     * @param wmNews
     * @param status
     * @param reason
     */
    private void extractUpdate(WmNews wmNews, short status, String reason) {
        wmNews.setStatus(status);
        wmNews.setReason(reason);
        wmNewsMapper.updateById(wmNews);
    }

    public Map<String, Object> ExtractTextAndImage(WmNews wmNews) {
        //存储文本内容
        StringBuilder text = new StringBuilder();
        //存储图片
        List<String> image = new ArrayList<>();

        //前端传来的文章参数是content:[{type:"",value:""},{}]
        if (StringUtils.isNotBlank(wmNews.getContent())) {
            List<Map> maps = JSONArray.parseArray(wmNews.getContent(), Map.class);
            for (Map map : maps) {
                //文本
                if (map.get("type").equals("text")) {
                    text.append(map.get("value"));
                }
                //图片
                if (map.get("type").equals("image")) {
                    image.add((String) map.get("value"));
                }
            }

        }
        //提取封面图片
        if (StringUtils.isNotBlank(wmNews.getImages())) {
            String[] split = wmNews.getImages().split(",");
            image.addAll(Arrays.asList(split));
        }

        //封装返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("text", text.toString());
        result.put("images", image);
        return result;
    }




}
